const bucket = new Set()

const data = { text: 'hello world' }

// 副作用注册函数
let activeEffect // 用于标记，因为需要手动执行一次effect(fn)，fn中会触发get操作，收集effect的fn
function effect(fn) {
  activeEffect = fn
  fn()
}

const obj = new Proxy(data, {
  // 拦截读取操作
  get(target, key) {
    // 只触发一次依赖收集
    if (activeEffect) {
      bucket.add(activeEffect)
    }
    return Reflect.get(target, key)
  },
  // 拦截设置操作
  set(target, key, val) {
    Reflect.set(target, key, val)
    bucket.forEach((fn) => fn())
    return true
  },
})

// 注册effect函数
effect(function listenText() {
  console.count('listenText') // 打印两次，第一次是在effect的注册时的fn(), 第二次是setTimeout中修改了text导致
  document.body.innerText = obj.text
})
setTimeout(() => {
  obj.anotherText = '我变化了' // 修改任意属性，都会触发set操作，导致effect函数listenText执行了
  /*
  这就引发了一个问题，如果修改的数据属性并不是effect函数监听的，还是会触发effect的不必要的执行
  要解决这个问题，就需要将effect函数和被操作的数据字段之间建立明确的联系
  */
}, 2000)
